package cc.blynk.server.core.model.auth; import cc.blynk.server.Limits; import cc.blynk.server.core.session.HardwareStateHolder; import cc.blynk.server.core.session.StateHolderBase; import cc.blynk.server.handlers.BaseSimpleChannelInboundHandler; import cc.blynk.utils.ServerProperties; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelPromise; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.core.LoggerContext; import org.apache.logging.log4j.core.config.Configuration; import org.openjdk.jmh.annotations.*; import java.util.Collections; import java.util.concurrent.TimeUnit; @BenchmarkMode(Mode.AverageTime) @OutputTimeUnit(TimeUnit.NANOSECONDS) @State(Scope.Thread) @Fork(1) @Warmup(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS) @Measurement(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS) public class SessionPerfTest { static final int DASH_ID = 1; Session session1; Session session2; Session session3; Session session4; int i1; int i2; int i3; int i4; @Setup public void setup() { // disable logging LoggerContext ctx = (LoggerContext) LogManager.getContext(false); Configuration conf = ctx.getConfiguration(); conf.getLoggerConfig(LogManager.ROOT_LOGGER_NAME).setLevel(org.apache.logging.log4j.Level.OFF); ctx.updateLoggers(conf); // create handler with HardwareStateHolder User user = new User(); HardwareStateHolder hardwareStateHolder = new HardwareStateHolder(0, DASH_ID, user, "1"); // create 1 hardware channel and a session session1 = new Session(null); session1.hardwareChannels.add(new EmbeddedChannel(newChannelHandler(hardwareStateHolder))); // create two hardware channels and a session session2 = new Session(null); session2.hardwareChannels.add(new EmbeddedChannel(newChannelHandler(hardwareStateHolder))); session2.hardwareChannels.add(new EmbeddedChannel(newChannelHandler(hardwareStateHolder))); // create 3 hardware channels and a session session3 = new Session(null); session3.hardwareChannels.add(new EmbeddedChannel(newChannelHandler(hardwareStateHolder))); session3.hardwareChannels.add(new EmbeddedChannel(newChannelHandler(hardwareStateHolder))); session3.hardwareChannels.add(new EmbeddedChannel(newChannelHandler(hardwareStateHolder))); // create 4 hardware channels and a session session4 = new Session(null); session4.hardwareChannels.add(new EmbeddedChannel(newChannelHandler(hardwareStateHolder))); session4.hardwareChannels.add(new EmbeddedChannel(newChannelHandler(hardwareStateHolder))); session4.hardwareChannels.add(new EmbeddedChannel(newChannelHandler(hardwareStateHolder))); session4.hardwareChannels.add(new EmbeddedChannel(newChannelHandler(hardwareStateHolder))); } @Benchmark public void sendMessageToHardware_1Channel() { session1.sendMessageToHardware(DASH_ID, (short) i1, i1, "body:" + (i1++)); } @Benchmark public void sendMessageToHardware_2Channels() { session2.sendMessageToHardware(DASH_ID, (short) i2, i2, "body:" + (i2++)); } @Benchmark public void sendMessageToHardware_3Channels() { session3.sendMessageToHardware(DASH_ID, (short) i3, i3, "body:" + (i3++)); } @Benchmark public void sendMessageToHardware_4Channels() { session4.sendMessageToHardware(DASH_ID, (short) i4, i4, "body:" + (i4++)); } @TearDown public void teardown() { session1.closeAll(); session2.closeAll(); session3.closeAll(); session4.closeAll(); } private ChannelHandler newChannelHandler(final HardwareStateHolder hardwareStateHolder) { return new BaseSimpleChannelInboundHandler<Object>(Object.class, new Limits(new ServerProperties(Collections.emptyMap()))) { @Override public void messageReceived(ChannelHandlerContext ctx, Object msg) { throw new UnsupportedOperationException(); } @Override public StateHolderBase getState() { return hardwareStateHolder; } }; } private class EmbeddedChannel extends io.netty.channel.embedded.EmbeddedChannel { public EmbeddedChannel(ChannelHandler... handlers) { super(handlers); } @Override public ChannelFuture writeAndFlush(Object msg) { return null; } @Override public ChannelFuture writeAndFlush(Object msg, ChannelPromise promise) { return null; } } }